//
// Created by 匡涂上青 on 2021/8/8.
//

#include "FPSCamera.h"

FPSCamera::FPSCamera(kgl::Ref<kgl::Transform> camera_transform, kgl::Ref<kgl::PerspectiveCamera> camera)
        : trans_ca(std::move(camera_transform)), camera(std::move(camera)), pitch(0.0f), yaw(90.0f),
          last_cursor_pos({kgl::Input::GetMousePosX(), kgl::Input::GetMousePosY()}) {
}

void FPSCamera::OnSetup() {
    trans_ca->position = {0, 0, 0};
    trans_ca->rotation = glm::rotation(
            glm::vec3{0.0f, 0.0f, -1.0f},
            glm::vec3{glm::cos(glm::radians(yaw)) * glm::cos(glm::radians(pitch)),
                      glm::sin(glm::radians(pitch)),
                      -glm::sin(glm::radians(yaw)) * glm::cos(glm::radians(pitch))}
    );
    last_cursor_pos = {kgl::Input::GetMousePosX(), kgl::Input::GetMousePosY()};
    kgl::singleton<kgl::Application>::getInstance()->GetWindow().addEventCallback([this](kgl::Event &ev) {
        kgl::EventDispatcher dispatcher(ev);
        dispatcher.Dispatch<kgl::MouseButtonPressedEvent>([this](kgl::MouseButtonPressedEvent &ev) {
            if (ev.button == kgl::Mouse::Button1) {
                last_cursor_pos = {kgl::Input::GetMousePosX(), kgl::Input::GetMousePosY()};
            }
            return false;
        });
    });
}

void FPSCamera::OnUpdate() {
    if (kgl::Input::IsMouseButtonPressed(kgl::Mouse::Button1)) {
        yaw -= (kgl::Input::GetMousePosX() - last_cursor_pos.x) * 0.1f;
        pitch = glm::clamp(pitch - (kgl::Input::GetMousePosY() - last_cursor_pos.y) * 0.1f,
                           -89.9f, 89.9f);
        trans_ca->rotation = glm::rotation(
                glm::vec3{0.0f, 0.0f, -1.0f},
                glm::vec3{
                        glm::cos(glm::radians(yaw)) * glm::cos(glm::radians(pitch)),
                        glm::sin(glm::radians(pitch)),
                        -glm::sin(glm::radians(yaw)) * glm::cos(glm::radians(pitch))}
        );
        last_cursor_pos = {kgl::Input::GetMousePosX(), kgl::Input::GetMousePosY()};
    }

    if (kgl::Input::IsKeyPressed(kgl::Key::W)) { // Front
        trans_ca->position += get_front() * moveSpeed;
    }
    if (kgl::Input::IsKeyPressed(kgl::Key::S)) { // Back
        trans_ca->position -= get_front() * moveSpeed;
    }
    if (kgl::Input::IsKeyPressed(kgl::Key::A)) { // Left
        trans_ca->position -= get_right() * moveSpeed;
    }
    if (kgl::Input::IsKeyPressed(kgl::Key::D)) { // Right
        trans_ca->position += get_right() * moveSpeed;
    }
}

void FPSCamera::OnDestroy() {
}


glm::vec3 FPSCamera::get_front() const {
    return glm::normalize(glm::rotate(trans_ca->rotation, {0, 0, -1.0f}));
}

glm::vec3 FPSCamera::get_right() const {
    return glm::normalize(glm::cross(get_front(), {0, 1.0f, 0}));
}

glm::vec3 FPSCamera::get_up() const {
    return glm::normalize(glm::cross(get_right(), get_front()));
}
